package com.neusoft.neuiotms.dcom.task.maintain.impl;

import java.util.List;

import javax.annotation.PostConstruct;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.Subscribe;
import com.neusoft.bizcore.schedule.service.JobMgrService;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.dto.MaintainPlanDTO;
import com.neusoft.neuiotms.dcom.service.MaintainPlanService;
import com.neusoft.neuiotms.dcom.task.maintain.JobBuildService;
import com.neusoft.neuiotms.dcom.task.maintain.event.JobBuildEvent;
import com.neusoft.neuiotms.dcom.task.maintain.event.MaintainPlanDeleteEvent;
import com.neusoft.neuiotms.dcom.task.maintain.event.MaintainPlanUpdateEvent;
import com.neusoft.neuiotms.dcom.task.maintain.job.MaintainTaskCreateJob;

import lombok.extern.slf4j.Slf4j;

/**
 * @author WYS
 * @date 2020年7月27日 上午10:44:19
 */
@Slf4j
@Component
@Transactional
@Order(value = 3)
public class JobBuildServiceImpl implements JobBuildService, CommandLineRunner {

    @Autowired
    private JobMgrService jobMgrService;
    @javax.annotation.Resource(name = "modelUpdateEventBus")
    private AsyncEventBus modelUpdateEventBus;
    @Autowired
    private MaintainPlanService maintainPlanService;

    @PostConstruct
    public void init() {
        this.modelUpdateEventBus.register(this);
    }

    @Subscribe
    public void onModelUpdateEvent(final JobBuildEvent event) {
        this.build(event);
    }

    /**
     * 启动时重新构建一遍所有维护任务，任务来源为任务计划
     */
    @Override
    public void jobBuildAll() {
        JobBuildServiceImpl.log.info("Begin to build all maintain task jobs.");
        final long startAt = System.currentTimeMillis();
        final List<MaintainPlanDTO> plans = this.maintainPlanService.findAllEnabled();
        for (final MaintainPlanDTO plan : plans) {
            this.createJob(plan.getCode(), plan.getName(), plan.getPeriod());
        }
        JobBuildServiceImpl.log.info("end to build all maintain task jobs, elapsed {} ms",
                System.currentTimeMillis() - startAt);

    }

    @Override
    public void run(final String... args) throws Exception {
        this.jobBuildAll();

    }

    @Override
    public void build(final JobBuildEvent event) {
        if (event instanceof MaintainPlanUpdateEvent) {
            this.build((MaintainPlanUpdateEvent) event);
        }
        if (event instanceof MaintainPlanDeleteEvent) {
            this.build((MaintainPlanDeleteEvent) event);
        }
    }

    /**
     * 当维护计划创建/更新时触发Job创建
     *
     * @param event
     */
    private void build(final MaintainPlanUpdateEvent event) {
        if (event.isStatus()) {
            this.createJob(event.getName(), event.getGroup(), event.getPeriod());
        } else {
            this.removeJob(event.getName(), event.getGroup());
        }
    }

    /**
     * 当维护计划创建时触发Job创建
     *
     * @param event
     */
    private void build(final MaintainPlanDeleteEvent event) {
        if (!event.isStatus()) {
            this.removeJob(event.getName(), event.getGroup());
        }
    }

    /**
     * 创建job
     */
    private void createJob(final String name, final String group, final String cronExpression) {
        final boolean existed = this.jobMgrService.isExists(name, group);
        if (existed) {
            this.jobMgrService.rescheduleJob(name, group, 0L);
        } else {
            final String jobDesc = DCOMConstants.JOB_DESCRIPTION + name;
            final JobDetail jobDetail =
                    JobBuilder.newJob(MaintainTaskCreateJob.class).withIdentity(name, group)
                            .withDescription(jobDesc).build();
            this.jobMgrService.scheduleCronJob(name, cronExpression, jobDetail);
        }
    }

    /**
     * 删除Job
     */
    private void removeJob(final String name, final String group) {
        final boolean existed = this.jobMgrService.isExists(name, group);
        if (existed) {
            this.jobMgrService.pauseJob(name, group);
            this.jobMgrService.deleteJob(name, group);
        }
    }

}
